/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.diplomka.datalayer.daoimpl;

import cz.muni.fi.diplomka.datalayer.dao.AllianceDao;
import cz.muni.fi.diplomka.datalayer.entity.AllianceEntity;
import cz.muni.fi.diplomka.datalayer.util.DbConnector;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.cypher.javacompat.ExecutionResult;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;

/**
 *
 * @author Jakub Kutil
 */
public class AllianceDaoImpl implements AllianceDao {

    @Override
    public void addAlliance(AllianceEntity allianceEntity) {
        if (allianceEntity == null) {
            throw new IllegalArgumentException("Alliance Entity can't be null.");
        }
        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();

        try (Transaction t = gds.beginTx()) {

            String query = "MATCH (Alliance:Alliance) RETURN max(Alliance.id)";

            Long key = new Long(0);
            ExecutionResult result = engine.execute(query);
            Iterator<Long> number = result.columnAs("max(Alliance.id)");
            while (number.hasNext()) {
                key = number.next();
            }

            if (key == null) {
                key = new Long(0);
            }
            allianceEntity.setId(new Long(key + 1));

            Map<String, Object> params = new HashMap<>();

            params.put("id", allianceEntity.getId());
            params.put("name", allianceEntity.getName());

            query = "CREATE (Alliance: Alliance {id : {id}, name : {name}})";
            engine.execute(query, params);
            t.success();
        }
    }

    @Override
    public void editAlliance(AllianceEntity allianceEntity) {
        if (allianceEntity == null) {
            throw new IllegalArgumentException("Alliance Entity can not be null.");
        }

        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();

        try (Transaction t = gds.beginTx()) {

            Map<String, Object> params = new HashMap<>();

            params.put("id", allianceEntity.getId());
            params.put("name", allianceEntity.getName());

            String query = "MATCH (Alliance:Alliance { id : {id} }) SET Alliance.name = {name}";
            engine.execute(query, params);
            t.success();
        }
    }

    @Override
    public void deleteAlliance(Long allianceId) {
        if (allianceId == null) {
            throw new IllegalArgumentException("Alliance Id can't be null.");
        }
        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();

        try (Transaction t = gds.beginTx()) {

            Map<String, Object> params = new HashMap<>();

            params.put("id", allianceId);

            String query = "MATCH (Alliance:Alliance { id : {id} }) DELETE Alliance";
            engine.execute(query, params);
            t.success();
        }
    }

    @Override
    public List<AllianceEntity> getAllAlliances() {
        List<AllianceEntity> allianceList = new ArrayList<>();

        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();


        try (Transaction t = gds.beginTx()) {

            String query = "MATCH (Alliance:Alliance) RETURN Alliance";
            ExecutionResult result = engine.execute(query);
            Iterator<Node> alliances = result.columnAs("Alliance");
            while (alliances.hasNext()) {
                Node node = alliances.next();
                AllianceEntity allianceEntity = new AllianceEntity();
                allianceEntity.setId(new Long(node.getProperty("id").toString()));
                allianceEntity.setName(node.getProperty("name").toString());

                allianceList.add(allianceEntity);
            }
            t.success();
        }
        return allianceList;
    }

    @Override
    public AllianceEntity getAllianceByName(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Name can not be null.");
        }
        AllianceEntity allianceEntity = new AllianceEntity();
        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();


        try (Transaction t = gds.beginTx()) {
            Map<String, Object> params = new HashMap<>();

            params.put("name", name);

            String query = "MATCH (Alliance:Alliance { name: {name} }) RETURN Alliance";
            ExecutionResult result = engine.execute(query, params);

            Iterator<Node> alliances = result.columnAs("Alliance");
            while (alliances.hasNext()) {
                Node node = alliances.next();
                allianceEntity.setId(new Long(node.getProperty("id").toString()));
                allianceEntity.setName(node.getProperty("name").toString());
            }

            t.success();
        }
        return allianceEntity;
    }

    @Override
    public AllianceEntity getAllianceOfPlayer(Long playerId) {
        if (playerId == null) {
            throw new IllegalArgumentException("Player Id can not be null.");
        }
        AllianceEntity allianceEntity = new AllianceEntity();
        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();


        try (Transaction t = gds.beginTx()) {
            Map<String, Object> params = new HashMap<>();

            params.put("playerId", playerId);

            String query = "MATCH (Player:Player {id : {playerId}})-[r:BELONGS]->(Alliance:Alliance) "
                    + "RETURN Alliance";
            ExecutionResult result = engine.execute(query, params);

            Iterator<Node> alliance = result.columnAs("Alliance");
            while (alliance.hasNext()) {
                Node node = alliance.next();
                allianceEntity.setId(new Long(node.getProperty("id").toString()));
                allianceEntity.setName(node.getProperty("name").toString());
            }

            t.success();
        }
        return allianceEntity;
    }
}
